#include "YaRRIncludes.h"


/************************************** Polite Request ***************************************
** I have put a lot of time and effort into YaRR. If you want to use some of the source     **
** please tell me. Anything used from YaRR must be open source, as is scripts.dll.          **
***************************************** Thank you *****************************************/


Stacker<Task *> *YaRRWorker::Tasks = 0;
CRITICAL_SECTION YaRRWorker::Mutex;
void *YaRRWorker::WorkerObj = 0;

DWORD __stdcall YaRRWorker::Worker(void *)
{
	while(1)
	{
		EnterCriticalSection(&Mutex);
		Task *const*t__ = Tasks->At(0);
		if(t__)
		{
			Task *t_ = *t__;
			if(t_->Count-- >= 1)
			{
				if(strcmp(t_->Name, "CALL") == 0)
				{
					unsigned int ret = t_->CALL(t_->Param);
					if(ret != 0)			
					{						
						t_->Count = ret;
						Tasks->Push(t_);
					}
					else
					{
						if(t_->Param)
						{	
							CDealloc(t_->Param);
						}
						CDealloc(t_);
					}
				}
				Tasks->Erase(0);
			}
			
		}
		Sleep(0);
		LeaveCriticalSection(&Mutex);
		Sleep(1);
	}
	return 0;
}

void YaRRWorker::Addtask(Task &t_)
{
	DLOG;
	EnterCriticalSection(&Mutex);
	Task *t = Alloc(Task);
	*t = t_;
	Tasks->Push(t);
	LeaveCriticalSection(&Mutex);
}

void YaRRWorker::Startup()
{
	DLOG;
	InitializeCriticalSection(&Mutex);
	Tasks = Alloc(Stacker<Task *>);
	if(!WorkerObj)
	{
		WorkerObj = CreateThread(NULL, NULL, Worker, NULL, NULL, NULL);
	}
	
	
}

void YaRRWorker::Shutdown()
{
	DLOG;
	if(!Tasks)
	{
		return;
	}
	EnterCriticalSection(&Mutex);

	IterateStack(x, Task *, Tasks)
	{

		if(x->Param)
		{	
			CDealloc(x->Param);
		}
		CDealloc(x);
	}

	if(WorkerObj)
	{
		TerminateThread(WorkerObj, 0);
		CloseHandle(WorkerObj);
	}
	WorkerObj = 0;
	LeaveCriticalSection(&Mutex);
	DeleteCriticalSection(&Mutex);

	Dealloc(Stacker<Task *>, Tasks);
	Tasks = 0;
}

char YaRRWorker::Flags()
{
	DLOG;
	char ret = 0;
	if(WorkerObj)
	{
		ret |= WORKER_RUNNING;
	}
	else
	{
		return 0;
	}

	if(Tasks->Length() == 0)
	{
		ret |= WORKER_IDLE;
	}
	else
	{
		ret |= WORKER_BUSY;
	}
	LeaveCriticalSection(&Mutex);
	return ret;
}